#include "GodRayRenderer.h"
#include "ResourceManager.h"
#include "Engine.h"
#include "GameState.h"
#include "Camera.h"

/* Creation, Shutdown */
GodRayRenderer::GodRayRenderer() : 
    m_shouldShadowMap(false),
    m_lightViewMatrix(NULL),
    m_lightProjMatrix(NULL),
    m_lightPositionScreenSpace(0,0),
    m_lightPositionWorldSpace(NULL),
    m_shadowMap(NULL),
    m_shouldAddNoise(false),
    m_noiseTexture(NULL),
    m_subtractedLightTexture(NULL),
    m_LightWithNoise(NULL),
    m_shouldGodRay(false),
    m_lightTextureWorld(NULL),
    m_darkPassTexture(NULL),
    m_addititiveDarkPass(NULL),
    m_godRayTexture(NULL),
    m_finalTexture(NULL),
    m_sceneTexture(NULL),
    m_gDensity(0.0f),
    m_gIllumDecay(0.0f),
    m_gWeight(0.0f),
    m_gDecay(0.0f),
    m_gExposure(0.0f),
    m_gTHold(0.0f),
    m_gVal(0.0f),
    m_gCosTheta(0.0f),
    m_numGodRayPasses(0),
    m_fullScreenQuad(NULL),
    m_sunShape(NULL),
    m_usingSunMesh(false),
    m_lightSourceTexture(false),
    m_usingExternalTexture(false),
    m_effect(NULL),
    m_shouldSkyBox(false),
    m_sunRotation(0.0f),
    m_lightDirectionScreenSpace(0,0)
{}
void GodRayRenderer::Initialise(ID3DXEffect* effect, D3DXVECTOR3* lightPosWorldSpace,
    int screenX, int screenY, D3DFORMAT textureFormat,int shadowMapSize,
    bool shouldShadowMap, D3DXMATRIXA16* lightTESTiew, D3DXMATRIXA16* lightProj,
    bool shouldGodRay, bool externalTexture, bool externalMesh,int numPasses,
    DirectXMesh* sunShape, Texture sunTexture,
    Texture ptrToTexture, bool addNoise, Texture noiseTex, bool skyBox)
{   
    m_shouldSkyBox = skyBox;
    m_shouldAddNoise = addNoise;
    m_noiseTexture = noiseTex;
    m_gDensity = 0.6f;
    m_gIllumDecay  = 0.4f;
    m_gWeight = 0.15f;
    m_gDecay = 0.95f;
    m_gExposure = 0.6f;
    m_gTHold = 0.2f;
    m_gVal = 0.00005f;
    m_numGodRayPasses = numPasses;

    m_usingExternalTexture = externalTexture;
    m_usingSunMesh = externalMesh;
    m_sunShape = sunShape;
    m_sunTexture = sunTexture;
    m_lightSourceTexture = ptrToTexture;
    m_lightViewMatrix = lightTESTiew;
    m_lightProjMatrix = lightProj;
    m_shouldShadowMap = shouldShadowMap;
    m_shadowMapSize = shadowMapSize;
    m_effect = effect;
    m_lightPositionWorldSpace = lightPosWorldSpace;
    m_shouldGodRay = shouldGodRay;
    //we have no light source!
    if(!m_usingSunMesh && !m_usingExternalTexture)
        m_shouldGodRay = false;

    int notused = 0;
    m_fullScreenQuad = Engine::Instance()->CreateTexturedQuad(&notused);

    //create the scene texture
    TEST(Engine::Instance()->GetDevice()->CreateTexture( screenX, screenY,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_sceneTexture,
        NULL ));
    //create the final texture
    TEST(Engine::Instance()->GetDevice()->CreateTexture( screenX, screenY,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_finalTexture,
        NULL ));

    if(shouldShadowMap)
        CreateShadowTexture();

    //create the black pass texture here
    TEST(Engine::Instance()->GetDevice()->CreateTexture( screenX, screenY,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_darkPassTexture,
        NULL ));
    //create the light texture pass here
    TEST(Engine::Instance()->GetDevice()->CreateTexture( screenX/4, screenY/4,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_lightTextureWorld,
        NULL ));
    
    //create the additive dark pass texture here
    TEST(Engine::Instance()->GetDevice()->CreateTexture(screenX/2, screenY/2,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_addititiveDarkPass,
        NULL ));
   
    //Create the god ray texture here
    TEST(Engine::Instance()->GetDevice()->CreateTexture(screenX, screenY,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_godRayTexture,
        NULL ));
    //create the subtracted light texture
    TEST(Engine::Instance()->GetDevice()->CreateTexture(screenX/4, screenY/4,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_subtractedLightTexture,
        NULL ));
    
    //create the texture with the added noise
    TEST(Engine::Instance()->GetDevice()->CreateTexture(screenX/2, screenY/2,
        0, D3DUSAGE_RENDERTARGET,
        textureFormat,
        D3DPOOL_DEFAULT, 
        &m_LightWithNoise,
        NULL ));
}
void GodRayRenderer::InitialiseSkyBox(   int size_x, int size_y, int size_z,
    float pos_x, float pos_y, float pos_z)
{
    //make the skybox buffers, and set tghe textures
    m_skyBox.InitializeBox(size_x,size_y,size_z, pos_x,pos_y,pos_z);
    m_skyBox.SetTextures(   GET_TEXTURE("box_floor.png"),
                            GET_TEXTURE("box_top.png"),
                            GET_TEXTURE("box_0.png"),
                            GET_TEXTURE("box_1.png"),
                            GET_TEXTURE("box_2.png"),
                            GET_TEXTURE("box_3.png"));
}
void GodRayRenderer::InitialiseSkyDome( float pos_x, float pos_y, float pos_z, int r )
{
    //make the skybox buffers, and set tghe textures
    m_skyBox.InitializeDome(pos_x,pos_y,pos_z,r);
    m_skyBox.SetTextures(   GET_TEXTURE("box_floor.png"),
                            GET_TEXTURE("box_top.png"),
                            GET_TEXTURE("box_0.png"),
                            GET_TEXTURE("box_1.png"),
                            GET_TEXTURE("box_2.png"),
                            GET_TEXTURE("box_3.png"));
}
void GodRayRenderer::ShutDown()
{
    if(m_sceneTexture)
        m_sceneTexture->Release();
    if(m_fullScreenQuad)
        m_fullScreenQuad->Release();
    if(m_finalTexture)
        m_finalTexture->Release();
    if(m_godRayTexture)
        m_godRayTexture->Release();
    if(m_addititiveDarkPass)
        m_addititiveDarkPass->Release();
    if(m_darkPassTexture)
        m_darkPassTexture->Release();
    if(m_LightWithNoise)
        m_LightWithNoise->Release();
    if(m_subtractedLightTexture)
        m_subtractedLightTexture->Release();
    if(m_shadowMap)
        m_shadowMap->Release();
    if(m_lightTextureWorld)
        m_lightTextureWorld->Release();
    m_skyBox.ShutDown();
}
/* Public Use Functions */
int GodRayRenderer::GetNumberOfPasses() const
{
    int ret = 1;
    if(m_shouldShadowMap)
        ret++;
    if(m_shouldGodRay)
        ret++;
    return ret;
}
bool GodRayRenderer::ShouldRenderThisPass( int whichPass )
{
    ManagePass(whichPass);

    //first pass is always true no matter what
    if(whichPass == 0)
        return true;

    //We only render two passes if we are adding god rays or shadows
    if((m_shouldGodRay || m_shouldShadowMap) && whichPass <= 1)
        return true;

    //we only render three passes if we are both shadow mapping AND god Ray-ing
    if((m_shouldGodRay && m_shouldShadowMap) && whichPass <= 2)
        return true;

    return false;
}
bool GodRayRenderer::ShouldRenderDebugOnly(int pass)
{
    // if its the first pass
    if(pass == 0)
    {
        //if we are'nt shadow mapping, render debug info
        if(!m_shouldShadowMap)
            return true;
        else 
            return false; //other whys, we are shadowmapping, and
    }                     //debug stuff doesnt need shadows!

    //we've done the shadow map, now render all
    if(m_shouldShadowMap && pass == 1)
        return true;

    return true;
}
/* Main implementation functions */
void GodRayRenderer::ManagePass(int whichPass)
{
    ResetRenderTarget();
    if(whichPass == 0)//either makes the map, or generates the scene
    {
        if(m_shouldShadowMap)
            GenerateShadowMap();
        if(!m_shouldShadowMap && m_shouldGodRay)
            GenerateScene(m_sceneTexture);
        if(!m_shouldShadowMap && !m_shouldGodRay)
            GenerateScene(m_finalTexture);
    }
    else if(whichPass == 1)//will either generatethe scene, or create the god ray texture
    {
        if(m_shouldShadowMap && !m_shouldGodRay)//last pass
        {
            GenerateScene(m_finalTexture);
        }
        else if(m_shouldGodRay && !m_shouldShadowMap) //last pass
        {
            GenerateGodRays();
        }
        else if(m_shouldGodRay && m_shouldShadowMap) //has to generate god rays next
        {
            GenerateScene(m_sceneTexture);
        }
    }
    else if(whichPass == 2)//only possible if we do shadows & god rays
    {
        GenerateGodRays();
    }
}
void GodRayRenderer::RenderFinalTexture()
{
    ResetRenderTarget();
    if(m_shouldGodRay)
    {
       GenerateFinalTexture();
    }
    RenderFullScreenQuad(m_finalTexture);
}
/* Set Functions for the render loop */
void GodRayRenderer::SetShadowMapping(bool shouldMap)
{
    m_shouldShadowMap = shouldMap;
    if(m_shouldShadowMap)
    {
        if(m_shadowMap)
            m_shadowMap->Release();
        CreateShadowTexture();
    }
}
void GodRayRenderer::SetNoiseAddition(bool addsRain)
{
    m_shouldAddNoise = addsRain;
}
/* Helper functions */
void GodRayRenderer::ResetRenderTarget()
{
    Engine::Instance()->ResetRenderTarget();
}
void GodRayRenderer::RenderAsCamera(bool shadowMapped)
{
    if(shadowMapped)
    {
        D3DXMATRIXA16 mViewToLightProj;
        D3DXMATRIXA16 identity;
        D3DXMatrixIdentity(&identity);
        mViewToLightProj = VIEW_MATRIX;
        D3DXMatrixInverse( &mViewToLightProj, NULL, &mViewToLightProj );
        D3DXMatrixMultiply( &mViewToLightProj, &mViewToLightProj, m_lightViewMatrix);
        D3DXMatrixMultiply( &mViewToLightProj, &mViewToLightProj, m_lightProjMatrix);
        TEST( m_effect->SetMatrix( "g_mViewToLightProj", &mViewToLightProj ) );
    }
    Vec3 cPos = Engine::Instance()->GetCurrentState()->GetCamera()->GetPos();
    D3DXVECTOR4 pos(cPos.m_x,cPos.m_y,cPos.m_z,1);
    TEST( m_effect->SetVector("gEyePosW", &pos));
    // Set the projection matrix, and the view (objects handle the world)
    TEST( m_effect->SetMatrix( "g_mProj", &PROJ_MATRIX));
    TEST( m_effect->SetMatrix( "g_mView", &VIEW_MATRIX));

    //set up the lights direction and position
    D3DXVECTOR3 v = *m_lightPositionWorldSpace;
    D3DXVECTOR4 v4;
    D3DXVec3Transform( &v4, &v, &VIEW_MATRIX );
    TEST( m_effect->SetVector( "gLightPosition", &v4 ) );
    D3DXVECTOR3 direction;
    D3DXVec3Normalize(&direction,m_lightPositionWorldSpace);
    direction *= -1;
    v4 = D3DXVECTOR4(direction,0); // Set w 0 so that the translation part doesn't come to play
    D3DXVec4Transform( &v4, &v4, &VIEW_MATRIX);  // Direction in view space
    D3DXVec3Normalize( ( D3DXVECTOR3* )&v4, ( D3DXVECTOR3* )&v4 );
    TEST( m_effect->SetVector( "g_vLightDir", &v4 ) );
}
void GodRayRenderer::SetRenderTarget( LPDIRECT3DTEXTURE9 target)
{
    Engine::Instance()->SetRenderTarget(target, true); 
}
void GodRayRenderer::RenderFullScreenQuad( LPDIRECT3DTEXTURE9 tex )
{
    //create an identity matrix
    D3DXMATRIXA16 identity;
    D3DXMatrixIdentity(&identity);
    //reset the matrixes in the shader
    TEST(m_effect->SetMatrix("g_mWorld", &identity));
    TEST(m_effect->SetMatrix("g_mView", &identity));
    TEST(m_effect->SetMatrix("g_mProj", &identity));

    if(tex)
    {
        // Apply the technique contained in the effect 
        TEST(m_effect->SetTechnique("Texture"));
        //set the texture
        TEST(m_effect->SetTexture("Diffuse", tex));
    }
    UINT passes = 0;
    TEST(Engine::Instance()->GetDevice()->SetVertexDeclaration(CustomVertex::s_dcl));
    TEST(Engine::Instance()->GetDevice()->SetStreamSource( 0, m_fullScreenQuad, 0, sizeof( CustomVertex ) ));


    TEST(m_effect->Begin( &passes, 0 ));
    for(unsigned int  iPass = 0; iPass < passes; iPass++ )
    {
        TEST(m_effect->BeginPass( iPass ));

        TEST(Engine::Instance()->GetDevice()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 ));

        TEST(m_effect->EndPass());
    }
    TEST(m_effect->End());
}
void GodRayRenderer::ClearCurrentTarget()
{
    TEST(Engine::Instance()->GetDevice()->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
        0xffffffff, 1.0f, 0 ));
}
void GodRayRenderer::GenerateShadowMap()
{
    //Set some shader stuff
    TEST(m_effect->SetTechnique("ShadowTech"));
    //Set the camera parameters 
    RenderAsLight();
    //Set the target to the final texture
    SetRenderTarget(m_shadowMap);
    //clear it
    ClearCurrentTarget();
}
void GodRayRenderer::GenerateScene( LPDIRECT3DTEXTURE9 targetTex )
{
    //Set some shader stuff
    TEST(m_effect->SetBool("g_isMapped", m_shouldShadowMap));
    if(m_shouldShadowMap)
    {
        TEST(m_effect->SetTexture("ShadowMap", m_shadowMap));
    }
    else
    {
        TEST(m_effect->SetTexture("ShadowMap", NULL));
    }
    //Set the camera parameters 
    RenderAsCamera(m_shouldShadowMap);
    //Set the target to the final texture
    SetRenderTarget(targetTex);
    //clear it
    TEST(Engine::Instance()->GetDevice()->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
        0x00000000, 1.0f, 0 ));
    if(m_shouldSkyBox)
    {
        TEST(m_effect->SetTechnique("SkyBox"));
        m_skyBox.Render(m_effect);
    }
    TEST(m_effect->SetTechnique("ShadowMapped"));
}
void GodRayRenderer::RenderAsLight()
{
    // Set the projection matrix, and the view (objects handle the world)
    TEST( m_effect->SetMatrix( "g_mProj", m_lightProjMatrix));
    TEST( m_effect->SetMatrix( "g_mView", m_lightViewMatrix));
}
void GodRayRenderer::CreateShadowTexture()
{
    TEST(Engine::Instance()->GetDevice()->CreateTexture( m_shadowMapSize, m_shadowMapSize,
        0, D3DUSAGE_RENDERTARGET,
        D3DFMT_R32F,
        D3DPOOL_DEFAULT, 
        &m_shadowMap,
        NULL ));
}
bool* GodRayRenderer::GetShadowMapBool()
{
    return &m_shouldShadowMap;
}
void GodRayRenderer::GenerateGodRays()
{
    //Generate the origional light texture
    SetRenderTarget(m_lightTextureWorld);
    //re clear it as black
    TEST(Engine::Instance()->GetDevice()->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
        0x00000000, 1.0f, 0 ));
    if(m_usingExternalTexture)
        GenerateLightTextureImage();
    else if(m_usingSunMesh)
        GenerateLightTextureSun();
    ResetRenderTarget();

    // Render the black siulluehhte 
    TEST(m_effect->SetTechnique("DarkPass"));
    RenderAsCamera(false);
    SetRenderTarget(m_darkPassTexture);
    //clear this as white
    ClearCurrentTarget();
}
void GodRayRenderer::GenerateFinalTexture()
{
    //The scene is in m_sceneTexture, and is either shadow mapped or not
    //the light source is either in m_lightTextureWorld, or m_downSizeTexture
    //The silhouette is in m_darkPassTexture
    //we may still need to add noise

    //render to the additive dark pass texture.
    SetRenderTarget(m_addititiveDarkPass);
    ClearCurrentTarget();
    //make sure we are using the right textures
    TEST(m_effect->SetTechnique("DarkBlend"));
    TEST(m_effect->SetTexture("LightTexture", m_lightTextureWorld));
    TEST(m_effect->SetTexture("DarkPassTexture", m_darkPassTexture));
    //This has to be the same as the clear color when generating the dark pass image!
    float arr[] = {1.0f, 1.0f, 1.0f};
    TEST(m_effect->SetFloatArray("gGlobalClearColor", arr, 3));
    /* Need a full screen render */
    RenderFullScreenQuad(NULL);
    /* Reset the render target */
    ResetRenderTarget();

    //we now have the silhouette with the added light texture, now to add god rays
    SetRenderTarget(m_godRayTexture);
    ClearCurrentTarget();
    //This sets the values in the shader
    CalculateLightPositionScreenSpace();
    TEST(m_effect->SetTechnique("GodRay"));
    TEST(m_effect->SetTexture("GodRayThis", m_addititiveDarkPass));
    TEST(m_effect->SetFloat("gDensity",m_gDensity));
    TEST(m_effect->SetFloat("gIllumDecay",m_gIllumDecay));
    TEST(m_effect->SetFloat("gWeight",m_gWeight));
    TEST(m_effect->SetFloat("gDecay",m_gDecay));
    TEST(m_effect->SetFloat("gExposure",m_gExposure));
    TEST(m_effect->SetFloat("gTHold",m_gTHold));
    TEST(m_effect->SetFloat("gVal",m_gVal));
    TEST(m_effect->SetInt("g_mPasses",m_numGodRayPasses));
    /* Need a full screen render */
    RenderFullScreenQuad(NULL);
    /* Reset the render target */
    ResetRenderTarget();

    if(m_shouldAddNoise)
    {
        //we now extract the light that was added to GodRays
        SetRenderTarget(m_subtractedLightTexture);
        ClearCurrentTarget();
        TEST(m_effect->SetTechnique("LightSample"));
        TEST(m_effect->SetTexture("LightAdded", m_godRayTexture));
        TEST(m_effect->SetTexture("LightSource", m_addititiveDarkPass));
        RenderFullScreenQuad(NULL);
        ResetRenderTarget();

        //we now add noise to the added light texture, and also add that back in to the god rays texture
        float arr0[] = {0.0f, 0.0f, 0.0f};
        TEST(m_effect->SetFloatArray("gGlobalClearColor", arr0, 3));
        TEST(m_effect->SetTexture("RainTexture", m_noiseTexture));
        TEST(m_effect->SetTexture("RainSource", m_subtractedLightTexture));
        TEST(m_effect->SetTexture("OrigionalLight", m_godRayTexture));
        SetRenderTarget(m_LightWithNoise);//this will contian the new god ray image with the added noise
        ClearCurrentTarget();
        TEST(m_effect->SetTechnique("BlendLightNoise"));
        RenderFullScreenQuad(NULL);
        ResetRenderTarget();
    }
    
    //add it all together
    SetRenderTarget(m_finalTexture);
    ClearCurrentTarget();
    float arr1[] = {1.0f, 1.0f, 1.0f};
    TEST(m_effect->SetFloatArray("gGlobalClearColor", arr1, 3));
    TEST(m_effect->SetTechnique("BlendTwoTextures"));
    if(m_shouldAddNoise)
    {
        TEST(m_effect->SetTexture("Blend1", m_LightWithNoise));
    }
    else
    {
        TEST(m_effect->SetTexture("Blend1", m_godRayTexture));
    }
    TEST(m_effect->SetTexture("Blend2", m_sceneTexture)); //this has to have the clear color special
    RenderFullScreenQuad(NULL);
    ResetRenderTarget();
}
void GodRayRenderer::GenerateLightTextureSun()
{
    //TEST(m_mainD3DDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE));
    D3DXMATRIXA16 world;
    //translate to the targets position 
    D3DXMatrixIdentity(&world);
    D3DXMatrixTranslation(&world,m_lightPositionWorldSpace->x,
                                 m_lightPositionWorldSpace->y,
                                 m_lightPositionWorldSpace->z);
    D3DXMATRIXA16 rot;
    m_sunRotation += 0.01f;
    if(m_sunRotation > M_PI)
        m_sunRotation = -(float)M_PI;
    D3DXMatrixRotationY(&rot,m_sunRotation);
    world =  rot*world;
    D3DXMATRIXA16 scale;
    D3DXMatrixScaling(&scale,1,1,1);
    world =  scale*world;
    D3DXMATRIXA16 worldTESTiew;
    TEST(m_effect->SetMatrix("g_mWorld",&world));
    TEST(m_effect->SetMatrix("g_mProj", &PROJ_MATRIX));
    TEST(m_effect->SetMatrix("g_mView", &VIEW_MATRIX));
    TEST(m_effect->SetTechnique("Texture"));
    TEST(m_effect->SetTexture("Diffuse", m_sunTexture));
    // Apply the technique contained in the effect 
    m_sunShape->Render(m_effect);
}
void GodRayRenderer::GenerateLightTextureImage()
{
    //translate to the targets position 
    D3DXMATRIXA16 world;
    D3DXMatrixIdentity(&world);
    D3DXMatrixTranslation(&world,m_lightPositionWorldSpace->x,
                                 m_lightPositionWorldSpace->y,
                                 m_lightPositionWorldSpace->z);
    D3DXMATRIXA16 scale;
    D3DXMatrixScaling(&scale,30,30,30);
    world =  scale*world;
    TEST(m_effect->SetMatrix("g_mWorld",&world));
    TEST(m_effect->SetMatrix("g_mProj", &PROJ_MATRIX));
    TEST(m_effect->SetMatrix("g_mView", &VIEW_MATRIX));
    TEST(m_effect->SetTechnique("Texture"));
    TEST(m_effect->SetTexture("Diffuse", m_lightSourceTexture));

    TEST(Engine::Instance()->GetDevice()->SetVertexDeclaration(CustomVertex::s_dcl));
    TEST(Engine::Instance()->GetDevice()->SetStreamSource( 0, m_fullScreenQuad, 0, sizeof( CustomVertex ) ));

    UINT passes = 0;
    TEST(m_effect->Begin( &passes, 0 ));
    for(unsigned int  iPass = 0; iPass < passes; iPass++ )
    {
        TEST(m_effect->BeginPass( iPass ));

        TEST(Engine::Instance()->GetDevice()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 ));

        TEST(m_effect->EndPass());
    }
    TEST(m_effect->End());
}  
void GodRayRenderer::CalculateLightPositionScreenSpace()
{
    //translate to the targets position 
    D3DXMATRIXA16 world;
    D3DXMatrixIdentity(&world);
    //create a world, view, projection matrix
    D3DXMATRIX worldViewProj;
    D3DXMatrixMultiply(&worldViewProj, &world, &VIEW_MATRIX);
    D3DXMatrixMultiply(&worldViewProj, &worldViewProj, &PROJ_MATRIX);
    /* Calculating the lights position in screen space */
    D3DXVECTOR4 lightPosW(*m_lightPositionWorldSpace,1);
    D3DXVec4Transform(&lightPosW, &lightPosW, &worldViewProj);
    D3DXVECTOR3 lightPosHom(lightPosW.x / lightPosW.w,lightPosW.y / lightPosW.w,lightPosW.z / lightPosW.w);
    D3DXVECTOR2 screenPos(lightPosHom.x /= lightPosHom.z, lightPosHom.y /= lightPosHom.z );

    //the following brings the CPU co-ordinate into shader screen space
    screenPos.x = ((screenPos.x / 2.0f) + 0.5f);
    screenPos.y = 1 - ( (screenPos.y / 2.0f) + 0.5f);
    m_lightPositionScreenSpace = screenPos;
    m_lightPositionScreenSpace += m_lightDirectionScreenSpace;
    TEST(m_effect->SetValue("gLightPos",&m_lightPositionScreenSpace,sizeof(D3DXVECTOR2)));
    TEST(m_effect->SetValue("gLightPosition",m_lightPositionWorldSpace, sizeof(D3DXVECTOR3))); 
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetSceneTexture()
{
    return m_sceneTexture;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetDarkPassTexture()
{
    return m_darkPassTexture;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetLightTexture()
{
    return m_lightTextureWorld;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetAdititveTexture()
{
    return m_addititiveDarkPass;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetGodRayTexture()
{
    return m_godRayTexture;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetShadowMap()
{
    return m_shadowMap;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetFinalTexture()
{
    return m_finalTexture;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetSubtractedLightTexture()
{
    return m_subtractedLightTexture;
}
LPDIRECT3DTEXTURE9 GodRayRenderer::GetGodRayWithNoiseTexture()
{
    return m_LightWithNoise;
}
void GodRayRenderer::TranslateNoiseTexture( float amount )
{
    m_gVal -= amount;
    if(m_gVal < -1.0f)
        m_gVal = 1;
    TEST(m_effect->SetFloat("gVal", m_gVal));
}
bool* GodRayRenderer::GetAddingNoiseBool()
{
    return &m_shouldAddNoise;
}
bool* GodRayRenderer::GetGodRayBool()
{
    return &m_shouldGodRay;
}
bool* GodRayRenderer::GetSkyBoxBool()
{
    return &m_shouldSkyBox;
}
bool GodRayRenderer::GetUseExternalTextureBool()const 
{
    return m_usingExternalTexture;
}
bool GodRayRenderer::GetUseMeshBool()const 
{
    return m_usingSunMesh;
}
void GodRayRenderer::ChangeLightSource()
{
    m_usingExternalTexture = !m_usingExternalTexture;
    m_usingSunMesh = !m_usingSunMesh;
}
int* GodRayRenderer::GetGodRayPasses()
{
    return &m_numGodRayPasses;
}
SkyBox* GodRayRenderer::GetSkyBox()
{
    return &m_skyBox;
}
